package main

import "fmt"

func main() {

	//	todo 切片是golang中一种特殊的数据类型
	//	切片随处可见，是一种数据类型上的抽象，切片是引用数据类型，片段可以是整个数组，或者是一些项的子集，终止索引不包括再切片内，切片提供了跟强大的能力和便捷

	//	定义切片
	sliceP()
	fmt.Println("============================================")
	// 创建切片，遍历切片
	createSlice()
	fmt.Println("============================================")
	//	切片不可以直接使用
	cutSlice()
	//  切片的拷贝
	copySlice()
}
func sliceP() {
	//定义数组
	var intarr = [6]int{3, 6, 9, 1, 4, 7}
	//	切片是构建在数组之上

	//从0开始切，不包含3
	var slice = intarr[0:3]
	//	输出数组
	fmt.Println("intarr", intarr)
	//	输出切片
	fmt.Println("slice", slice)

	//	切片的元素长度
	fmt.Println("slice", len(slice))
	//	切片容量可以变化
	fmt.Println("slice", cap(slice))

	//	切片只是地址引用，如下地址是相同的
	fmt.Printf("数组下标为1的位置地址： %p", &intarr[1])
	fmt.Printf("切片中下标0位置的的地址：%p", &slice[1])

}

func createSlice() {

	//	定义一个切片  切片类型，切片长度，切片的容量
	slicee := make([]int, 4, 20)
	fmt.Println("slicee", slicee)
	fmt.Println("slicee的长度", len(slicee))
	fmt.Println("slicee的容量", cap(slicee))
	//	make内置函数创建切片，
	// make底层创建一个数组，对外不可见，所以不可以直接操作这个数组，需要通过slice去简介操作各个元素值，不可以直接维护数组。
	slicee[0] = 22
	slicee[1] = 34
	fmt.Println("slicee", slicee)

	fmt.Println("---------------------------------------------------------")
	//	切片的遍历
	slice2 := make([]int, 5, 20)
	slice2[0] = 11
	slice2[1] = 22
	slice2[2] = 33
	slice2[3] = 44
	slice2[4] = 55
	for i := 0; i < len(slice2); i++ {
		fmt.Printf("slice[%v] = %v \t", i, slice2[i])
	}

	fmt.Println("---------------------------------------------------------")

	for index, val := range slice2 {
		fmt.Printf("下标：%v 值：%v\t", index, val)
	}
}

func cutSlice() {
	//	切片还可以再次切片，元素仍然是同一内存空间
	//  底层原理，
	//  1.底层追加元素的时候对数组进行扩容，老数组扩容为新数组
	//  2.创建一个新数组，将老数组中的元素赋值到新数组中，再新数组中追加后来的元素
	//  3.slice2 底层数组的指向 指向的是新数组
	//  4.一般用完append凭借完成之后再给自己。

	var intarr = [6]int{1, 3, 5, 7, 9, 0}
	//	定义一个切片
	var slice1 = intarr[1:4]
	fmt.Println("slice1", slice1)
	newSlice1 := append(slice1, 11, 22, 33, 44)
	fmt.Println("newSlice1", newSlice1)
}

func copySlice() {
	//定义一个数组
	var a = []int{1, 3, 6, 8, 9}
	//	定义一个切片
	var b = make([]int, 10)
	//拷贝
	copy(b, a)
	// 长度为10，没有填写的以默认值填充
	fmt.Println(b)
}
